package com.dj.mingkong.portal.biz.service.music.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dj.mingkong.common.enums.StatusEnum;
import com.dj.mingkong.common.exception.ValidateException;
import com.dj.mingkong.common.infrastructure.base.dto.context.UserInfoContext;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicianEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicianFansEo;
import com.dj.mingkong.common.microservice.UserContext;
import com.dj.mingkong.common.util.AssertUtils;
import com.dj.mingkong.common.util.SmartBeanCopy;
import com.dj.mingkong.portal.biz.controller.music.vo.request.MusicianFansAddVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.MusicianFansCancelVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.MusicianFansQueryVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.MusicianFansUserQueryVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.MusicianFansDetailVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.MusicianFansUserVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.MusicianFansVo;
import com.dj.mingkong.portal.biz.core.base.context.UserContextHolder;
import com.dj.mingkong.portal.biz.repository.database.music.MusicianFansRepository;
import com.dj.mingkong.portal.biz.repository.database.music.MusicianRepository;
import com.dj.mingkong.portal.biz.service.music.MusicianFansService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

/**
 * 关注音乐人服务实现类
 *
 * @author zenglonghui
 * @date: 2022/8/25 10:50
 */
@Slf4j
@Service("musicianFansService")
public class MusicianFansServiceImpl implements MusicianFansService {
    @Resource
    private MusicianFansRepository musicianFansRepository;
    @Resource
    private UserContextHolder userContextHolder;
    @Resource
    private MusicianRepository musicianRepository;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void follow(MusicianFansAddVo addVo) {
        final MusicianEo musicianEo = musicianRepository.getById(addVo.getMusicianId());
        AssertUtils.isNotNull(musicianEo, "musicianId invalid");
        final Optional<MusicianFansEo> eoOptional = musicianFansRepository
                .oneOptByUserIdAndMusicianId(UserContext.getUserId(), addVo.getMusicianId());
        eoOptional.ifPresentOrElse(musicianFansEo -> {
            if (StatusEnum.VALID.equalsIntVal(musicianFansEo.getStatus())) {
                musicianFansEo.setStatus(StatusEnum.INVALID.getIntVal());
                musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() - 1));
            } else {
                musicianFansEo.setStatus(StatusEnum.VALID.getIntVal());
                musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() + 1));
            }
            musicianFansEo.setType(addVo.getType());
            musicianFansRepository.updateById(musicianFansEo);
        }, () -> {
            final MusicianFansEo fansEo = MusicianFansEo.builder().musicianId(addVo.getMusicianId())
                    .status(StatusEnum.VALID.getIntVal()).userId(UserContext.getUserId())
                    .type(addVo.getType()).build();
            musicianFansRepository.save(fansEo);
            musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() + 1));
        });
    }

    @Override
    public MusicianFansDetailVo getMusicianFans(Long musicianId) {
        final UserInfoContext currentUser = userContextHolder.getCurrentUser();
        if (Objects.isNull(currentUser)) {
            return MusicianFansDetailVo.builder().musicianId(musicianId).status(StatusEnum.INVALID.getIntVal())
                    .build();
        }
        final Optional<MusicianFansEo> eoOptional = musicianFansRepository
                .oneOptByUserIdAndMusicianId(currentUser.getId(), musicianId);

        if (eoOptional.isEmpty()) {
            return MusicianFansDetailVo.builder().musicianId(musicianId).status(StatusEnum.INVALID.getIntVal())
                    .userId(currentUser.getId()).build();
        }
        return SmartBeanCopy.copy(eoOptional.get(), MusicianFansDetailVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(MusicianFansAddVo addVo) {
        final MusicianEo musicianEo = musicianRepository.getById(addVo.getMusicianId());
        AssertUtils.isNotNull(musicianEo, "musicianId invalid");
        final Optional<MusicianFansEo> eoOptional = musicianFansRepository
                .oneOptByUserIdAndMusicianId(UserContext.getUserId(), addVo.getMusicianId());
        eoOptional.ifPresentOrElse(musicianFansEo -> {
            if (StatusEnum.VALID.equalsIntVal(musicianFansEo.getStatus())) {
                throw new ValidateException("已关注");
            }
            musicianFansEo.setStatus(StatusEnum.VALID.getIntVal());
            musicianFansEo.setType(addVo.getType());
            musicianFansRepository.updateById(musicianFansEo);
            musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() + 1));
        }, () -> {
            final MusicianFansEo fansEo = MusicianFansEo.builder().musicianId(addVo.getMusicianId())
                    .status(StatusEnum.VALID.getIntVal()).userId(UserContext.getUserId())
                    .type(addVo.getType()).build();
            musicianFansRepository.save(fansEo);
            musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() + 1));
        });
    }

    @Override
    public Page<MusicianFansVo> pageByVo(MusicianFansQueryVo queryVo) {
        return musicianFansRepository.getMapper().listPage(Page.of(queryVo.getPage(), queryVo.getPageSize()), queryVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancel(MusicianFansCancelVo cancelVo) {
        final MusicianEo musicianEo = musicianRepository.getById(cancelVo.getMusicianId());
        AssertUtils.isNotNull(musicianEo, "musicianEo invalid");
        Optional<MusicianFansEo> optional = musicianFansRepository.oneOptByUserIdAndMusicianId(UserContext.getUserId(), cancelVo.getMusicianId());
        optional.ifPresent(musicianFansEo -> {
            if (StatusEnum.VALID.equalsIntVal(musicianFansEo.getStatus())) {
                musicianFansEo.setStatus(StatusEnum.INVALID.getIntVal());
                musicianFansRepository.updateById(musicianFansEo);
                musicianRepository.updateById(musicianEo.setFansCount(musicianEo.getFansCount() - 1));
            }
        });
    }

    @Override
    public Page<MusicianFansUserVo> pageUserByVo(MusicianFansUserQueryVo queryVo) {
        return musicianFansRepository.getMapper().listUserPage(Page.of(queryVo.getPage(), queryVo.getPageSize()), queryVo);
    }
}
